#pragma once
#include <iostream>
#include <queue>
#include <pthread.h>
template <class T>
class BlockQueue
{
#define defaultcap 5
public:
    BlockQueue()
    :_size(0),_cap(defaultcap)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_full_cond,nullptr);
        pthread_cond_init(&_empty_cond,nullptr);
    }
    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_full_cond);
        pthread_cond_destroy(&_empty_cond);
    }
    bool IsFull()
    {
        if(_size>=_cap)  return true;
        return false;
    }
    bool IsEmpty()
    {
        if(_size<=0)    return true;
        return false;
    }
    void EQueue(T& in)
    {
        pthread_mutex_lock(&_mutex);
        while(IsFull())
        {
            pthread_cond_wait(&_full_cond,&_mutex);
        }
        _blockqueue.push(in);
        _size++;
        pthread_cond_signal(&_empty_cond);
        pthread_mutex_unlock(&_mutex);
    }
    void Pop(T& out)
    {
        pthread_mutex_lock(&_mutex);
        while(IsEmpty())
        {
            pthread_cond_wait(&_empty_cond,&_mutex);
        }
        out = _blockqueue.front();
        _blockqueue.pop();
        _size--;
        pthread_cond_signal(&_full_cond);
        pthread_mutex_unlock(&_mutex);
    }


private:
    std::queue<T> _blockqueue;
    int _size;
    int _cap;
    pthread_mutex_t _mutex;
    pthread_cond_t _full_cond;
    pthread_cond_t _empty_cond;

};